using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Text.Json;
using Microsoft.EntityFrameworkCore;
using Book.Blog.Core.DTOs;
using Book.Blog.Core.Entities.Settings;
using Book.Blog.Core.Interfaces;

namespace Book.Blog.Infrastructure.Services
{
    public class SettingService : ISettingService
    {
        private readonly IRepository<SystemSetting> _settingRepository;

        public SettingService(IRepository<SystemSetting> settingRepository)
        {
            _settingRepository = settingRepository;
        }

        public async Task<IEnumerable<SettingDTO>> GetAllSettingsAsync()
        {
            var settings = await _settingRepository.Query()
                .Where(s => !s.IsDeleted)
                .Select(s => new SettingDTO
                {
                    Id = s.Id,
                    Key = s.Key,
                    Value = s.Value,
                    Description = s.Description,
                    Group = s.Group,
                    Type = s.Type,
                    CreatedAt = s.CreatedAt,
                    UpdatedAt = s.UpdatedAt
                })
                .ToListAsync();

            return settings;
        }

        public async Task<SettingDTO?> GetSettingByKeyAsync(string key)
        {
            var setting = await _settingRepository.Query()
                .Where(s => s.Key == key && !s.IsDeleted)
                .Select(s => new SettingDTO
                {
                    Id = s.Id,
                    Key = s.Key,
                    Value = s.Value,
                    Description = s.Description,
                    Group = s.Group,
                    Type = s.Type,
                    CreatedAt = s.CreatedAt,
                    UpdatedAt = s.UpdatedAt
                })
                .FirstOrDefaultAsync();

            return setting;
        }

        public async Task<IEnumerable<SettingGroupDTO>> GetSettingsByGroupAsync(string group)
        {
            var settings = await _settingRepository.Query()
                .Where(s => s.Group == group && !s.IsDeleted)
                .GroupBy(s => s.Group)
                .Select(g => new SettingGroupDTO
                {
                    Group = g.Key,
                    Settings = g.Select(s => new SettingDTO
                    {
                        Id = s.Id,
                        Key = s.Key,
                        Value = s.Value,
                        Description = s.Description,
                        Group = s.Group,
                        Type = s.Type,
                        CreatedAt = s.CreatedAt,
                        UpdatedAt = s.UpdatedAt
                    }).ToList()
                })
                .ToListAsync();

            return settings;
        }

        public async Task<SiteSettingsDTO> GetSiteSettingsAsync()
        {
            var settings = await _settingRepository.Query()
                .Where(s => s.Group == "Site" && !s.IsDeleted)
                .ToDictionaryAsync(s => s.Key, s => s.Value);

            return new SiteSettingsDTO
            {
                SiteName = settings.GetValueOrDefault("SiteName"),
                SiteDescription = settings.GetValueOrDefault("SiteDescription"),
                SiteKeywords = settings.GetValueOrDefault("SiteKeywords"),
                SiteLogo = settings.GetValueOrDefault("SiteLogo"),
                SiteFavicon = settings.GetValueOrDefault("SiteFavicon"),
                FooterText = settings.GetValueOrDefault("FooterText"),
                IsClosed = bool.TryParse(settings.GetValueOrDefault("IsClosed"), out bool isClosed) && isClosed,
                ClosedMessage = settings.GetValueOrDefault("ClosedMessage")
            };
        }

        public async Task<EmailSettingsDTO> GetEmailSettingsAsync()
        {
            var settings = await _settingRepository.Query()
                .Where(s => s.Group == "Email" && !s.IsDeleted)
                .ToDictionaryAsync(s => s.Key, s => s.Value);

            return new EmailSettingsDTO
            {
                SmtpServer = settings.GetValueOrDefault("SmtpServer"),
                SmtpPort = int.TryParse(settings.GetValueOrDefault("SmtpPort"), out int port) ? port : 587,
                SmtpUsername = settings.GetValueOrDefault("SmtpUsername"),
                SmtpPassword = settings.GetValueOrDefault("SmtpPassword"),
                FromEmail = settings.GetValueOrDefault("FromEmail"),
                FromName = settings.GetValueOrDefault("FromName")
            };
        }

        public async Task<StorageSettingsDTO> GetStorageSettingsAsync()
        {
            var settings = await _settingRepository.Query()
                .Where(s => s.Group == "Storage" && !s.IsDeleted)
                .ToDictionaryAsync(s => s.Key, s => s.Value);

            return new StorageSettingsDTO
            {
                Provider = settings.GetValueOrDefault("Provider", "Local"),
                LocalPath = settings.GetValueOrDefault("LocalPath", "wwwroot/uploads"),
                MaxFileSize = int.TryParse(settings.GetValueOrDefault("MaxFileSize"), out int maxSize) ? maxSize : 10,
                AllowedFileTypes = settings.GetValueOrDefault("AllowedFileTypes", "jpg,jpeg,png,gif")
            };
        }

        public async Task<SettingDTO> CreateSettingAsync(CreateSettingDTO dto)
        {
            var setting = new SystemSetting
            {
                Key = dto.Key,
                Value = dto.Value,
                Description = dto.Description,
                Group = dto.Group,
                Type = dto.Type
            };

            await _settingRepository.AddAsync(setting);

            return new SettingDTO
            {
                Id = setting.Id,
                Key = setting.Key,
                Value = setting.Value,
                Description = setting.Description,
                Group = setting.Group,
                Type = setting.Type,
                CreatedAt = setting.CreatedAt,
                UpdatedAt = setting.UpdatedAt
            };
        }

        public async Task<SettingDTO> UpdateSettingAsync(UpdateSettingDTO dto)
        {
            var setting = await _settingRepository.Query()
                .FirstOrDefaultAsync(s => s.Id == dto.Id && !s.IsDeleted);

            if (setting == null)
                throw new KeyNotFoundException($"Setting with ID {dto.Id} not found.");

            setting.Value = dto.Value;
            setting.Description = dto.Description;
            setting.Group = dto.Group;
            setting.Type = dto.Type;

            await _settingRepository.UpdateAsync(setting);

            return new SettingDTO
            {
                Id = setting.Id,
                Key = setting.Key,
                Value = setting.Value,
                Description = setting.Description,
                Group = setting.Group,
                Type = setting.Type,
                CreatedAt = setting.CreatedAt,
                UpdatedAt = setting.UpdatedAt
            };
        }

        public async Task<bool> BatchUpdateSettingsAsync(BatchUpdateSettingsDTO dto)
        {
            foreach (var item in dto.Settings)
            {
                var setting = await _settingRepository.Query()
                    .FirstOrDefaultAsync(s => s.Key == item.Key && !s.IsDeleted);

                if (setting != null)
                {
                    setting.Value = item.Value;
                    await _settingRepository.UpdateAsync(setting);
                }
            }

            return true;
        }

        public async Task<bool> DeleteSettingAsync(Guid id)
        {
            var setting = await _settingRepository.Query()
                .FirstOrDefaultAsync(s => s.Id == id && !s.IsDeleted);

            if (setting == null)
                return false;

            await _settingRepository.DeleteAsync(setting);
            return true;
        }

        private SettingDTO MapToDTO(SystemSetting setting)
        {
            return new SettingDTO
            {
                Id = setting.Id,
                Key = setting.Key,
                Value = setting.Value,
                Description = setting.Description,
                Group = setting.Group,
                Type = setting.Type,
                CreatedAt = setting.CreatedAt,
                UpdatedAt = setting.UpdatedAt
            };
        }

        public async Task<IEnumerable<SettingDTO>> GetPublicSettingsAsync()
        {
            var settings = await _settingRepository.Query()
                .Where(s => s.IsPublic && !s.IsDeleted)
                .OrderBy(s => s.Group)
                .ThenBy(s => s.SortOrder)
                .ToListAsync();

            return settings.Select(s => new SettingDTO
            {
                Id = s.Id,
                Key = s.Key,
                Value = s.Value,
                Description = s.Description,
                Group = s.Group,
                Type = s.Type,
                CreatedAt = s.CreatedAt,
                UpdatedAt = s.UpdatedAt
            });
        }

        public async Task<IEnumerable<SettingGroupDTO>> GetSettingGroupsAsync()
        {
            var settings = await _settingRepository.Query()
                .Where(s => !s.IsDeleted)
                .OrderBy(s => s.Group)
                .ThenBy(s => s.SortOrder)
                .ToListAsync();

            return settings
                .GroupBy(s => s.Group)
                .Select(g => new SettingGroupDTO
                {
                    Group = g.Key,
                    Settings = g.Select(s => new SettingDTO
                    {
                        Id = s.Id,
                        Key = s.Key,
                        Value = s.Value,
                        Description = s.Description,
                        Group = s.Group,
                        Type = s.Type,
                        CreatedAt = s.CreatedAt,
                        UpdatedAt = s.UpdatedAt
                    }).ToList()
                });
        }

        public async Task<bool> ResetToDefaultAsync()
        {
            // 删除所有现有设置
            var existingSettings = await _settingRepository.Query()
                .Where(s => !s.IsDeleted)
                .ToListAsync();
            foreach (var setting in existingSettings)
            {
                await _settingRepository.DeleteAsync(setting);
            }

            // 添加默认设置
            var defaultSettings = GetDefaultSettings();
            foreach (var setting in defaultSettings)
            {
                await _settingRepository.AddAsync(setting);
            }

            return true;
        }

        public async Task<bool> ValidateSettingValueAsync(string key, string value)
        {
            var setting = await _settingRepository.Query()
                .FirstOrDefaultAsync(s => s.Key == key && !s.IsDeleted);

            if (setting == null)
                return false;

            switch (setting.Type.ToLower())
            {
                case "number":
                    return decimal.TryParse(value, out _);
                case "boolean":
                    return bool.TryParse(value, out _);
                case "json":
                    try
                    {
                        System.Text.Json.JsonDocument.Parse(value);
                        return true;
                    }
                    catch
                    {
                        return false;
                    }
                default:
                    return true;
            }
        }

        private IEnumerable<SystemSetting> GetDefaultSettings()
        {
            return new List<SystemSetting>
            {
                new SystemSetting { Key = "Site.Name", Value = "Book Blog", Type = "String", Group = "Site", IsPublic = true, Description = "网站名称" },
                new SystemSetting { Key = "Site.Description", Value = "一个简单的博客系统", Type = "String", Group = "Site", IsPublic = true, Description = "网站描述" },
                new SystemSetting { Key = "Site.Keywords", Value = "博客,技术,生活", Type = "String", Group = "Site", IsPublic = true, Description = "网站关键词" },
                new SystemSetting { Key = "Site.Logo", Value = "/images/logo.png", Type = "String", Group = "Site", IsPublic = true, Description = "网站Logo" },
                new SystemSetting { Key = "Site.Favicon", Value = "/images/favicon.ico", Type = "String", Group = "Site", IsPublic = true, Description = "网站图标" },
                new SystemSetting { Key = "Site.Footer", Value = "© 2024 Book Blog. All rights reserved.", Type = "String", Group = "Site", IsPublic = true, Description = "页脚文本" },
                new SystemSetting { Key = "Email.SmtpServer", Value = "smtp.example.com", Type = "String", Group = "Email", IsPublic = false, Description = "SMTP服务器" },
                new SystemSetting { Key = "Email.Port", Value = "587", Type = "Number", Group = "Email", IsPublic = false, Description = "SMTP端口" },
                new SystemSetting { Key = "Email.Username", Value = "", Type = "String", Group = "Email", IsPublic = false, Description = "SMTP用户名" },
                new SystemSetting { Key = "Email.Password", Value = "", Type = "String", Group = "Email", IsPublic = false, Description = "SMTP密码" },
                new SystemSetting { Key = "Storage.Provider", Value = "Local", Type = "String", Group = "Storage", IsPublic = false, Description = "存储提供者" },
                new SystemSetting { Key = "Storage.LocalPath", Value = "wwwroot/uploads", Type = "String", Group = "Storage", IsPublic = false, Description = "本地存储路径" }
            };
        }
    }
} 